

use crate::cli::Cli;
use anyhow::{Context, Result};
use strsim::levenshtein;


use clap::{Command, CommandFactory, Parser};
use std::collections::BTreeSet;
use std::fs;
use std::path::Path;
use clap::builder::Str;
use dialoguer::Input;

pub fn all_subcommand_names() -> Vec<String> {
    let cmd = Cli::command();
    let mut out = BTreeSet::new();

    // 直接遍历顶层子命令
    for subcmd in cmd.get_subcommands() {
        collect_subcommands(subcmd, &[subcmd.get_name()], &mut out);
    }

    out.into_iter().collect()
}

fn collect_subcommands(cmd: &Command, cmd_path: &[&str] , out: &mut BTreeSet<String>) {

    if cmd.get_subcommands().next().is_none() {  // 非内部节点 才会加入out
        let current_name = format!("{}", cmd_path.join(" ") ) ;
        out.insert(current_name.clone());
    }

    for subcmd in cmd.get_subcommands() {
       let  mut new_cmd_path = cmd_path.to_vec() ;
        new_cmd_path.push(subcmd.get_name());
        collect_subcommands(subcmd, &new_cmd_path , out);
    }
}
pub fn find_similar_commands(target: &str, candidates: &[String], count: usize) -> Vec<String> {
    let mut scored: Vec<(f64, &String)> = candidates
        .iter()
        .map(|c| {
            let distance = levenshtein(target, c) as f64;
            let max_len = std::cmp::max(target.len(), c.len()) as f64;
            let similarity = 1.0 - (distance / max_len);
            (similarity, c)
        })
        .filter(|(s, _)| *s > 0.3)
        .collect();

    scored.sort_by(|(a, _), (b, _)| b.partial_cmp(a).unwrap());

    scored
        .into_iter()
        .take(count)
        .map(|(_, c)| c.clone())
        .collect()
}

pub fn extract_unknown_command(error_msg: &str) -> Option<&str> {
    if error_msg.starts_with("unrecognized subcommand '") {
        let cmd = error_msg.split("'").nth(1)?;
        Some(cmd)
    } else {
        None
    }
}


pub fn is_file_modified(source: &Path, dest: &Path) -> Result<bool> {
    let source_meta = fs::metadata(source).context("获取源文件元数据失败")?;
    let dest_meta = match fs::metadata(dest) {
        Ok(meta) => meta,
        Err(_) => return Ok(true),
    };

    if source_meta.len() != dest_meta.len() {
        return Ok(true);
    }

    let source_time = source_meta.modified().context("获取源文件修改时间失败")?;
    let dest_time = dest_meta.modified().context("获取目标文件修改时间失败")?;

    Ok(source_time > dest_time)
}

/// 辅助函数：收集多个 glob 模式（空输入结束）
pub fn collect_patterns(prompt: &str) -> Result<Vec<String>> {
    let mut patterns = Vec::new();
    eprintln!("\n{}（每行一个模式，直接回车结束）", prompt);
    loop {
        let input: String = Input::new()
            .allow_empty(true)
            .with_prompt(format!("模式（已添加 {} 个）", patterns.len()))
            .interact_text()
            .context("获取模式输入失败")?;
        let input = input.trim();
        if input.is_empty() {
            break;
        }
        patterns.push(input.to_string());
    }
    Ok(patterns)
}